package com.itheima.d2_reflect;

import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;

public class ObjectFrame {
    // 目标：保存任意对象的字段和其数据到文件中去
    public static void saveObject(Object obj) throws Exception {
        //要往文件中保存，应该用打印流。并且保存完一个对象的数据，接着还要在文件下面保存另一个对象的数据，所以要做追加
        //所以要包装一个低级管道FileOutputStream，然后加个true，到时候就能往这个文件中一个一个的往后追加对象的数据
        //弹幕：Junit测试情况下根目录是：src/....... 因为这里执行是使用Junit框架，相对路径的默认起点为模块路径，在运行/调试配置的Working directory处修改
        PrintStream ps = new PrintStream(new FileOutputStream("src\\data.txt", true));
        //弹幕有人说要再加一个true，不然会被覆盖。我没加也不会被覆盖   弹幕：第二个true默认是true,所以可以不写
        //PrintStream ps = new PrintStream(new FileOutputStream("src\\data.txt", true),true);
        // obj是任意对象，到底有多少个字段要保存。


        // 方式三：Class c3 = 对象.getClass(); 调用Object提供的方法：public Class getClass();
        Class c = obj.getClass();

        //怎么样知道这个对象是什么类型，我们可以拿到这个obj对象的类的类名
        String cName = c.getSimpleName();
        //然后再把类名信息打印到文件中，这样学生类和老师类就能分开，一目了然
        ps.println("---------------" + cName + "------------------------");

        // 2、从这个类中提取它的全部成员变量
        Field[] fields = c.getDeclaredFields();
        // 3、遍历每个成员变量。
        for (Field field : fields) {
            // 4、拿到成员变量的名字（字段名）
            String name = field.getName();

            // 5、拿到这个成员变量在对象中对应的数据。（字段值）
            field.setAccessible(true); // 禁止检查访问控制，记得把权限打开，避免私有的成员变量无法访问
            //  void set(Object obj, Object value)：          赋值
            //  Object get(Object obj)                       获取值
            //把调用saveObject方法给的形参obj，也就是取对象obj当前这个成员变量的值，直接把obj给get方法
            // 有异常直接抛出去，get方法取的obj对象的成员变量的值，是object类型。可以加一个“”空字符串转成字符串
            String value = field.get(obj) + "";
            ps.println(name + "=" + value);
            //然后把拿到的字段名和字段值往文件中保存，所以可以用一个打印流来往文件中保存

        }
        ps.close();
    }
}
